const toc = require("markdown-toc");

// 接下来对上面的数据进行一个转换

function transfer(flatArr) {
    const stack = []; // 模拟栈的结构
    const result = []; // 存放最终转换结果的数组

    /**
     * 创建 TOC 对象
     * @param {*} item 
     * @returns 
     */
    function createTOCItem(item) {
        return {
            name: item.content,
            anchor: item.slug,
            level: item.lvl,
            children: []
        }
    }

    function handleItem(item) {
        // 获取 stack 栈顶的元素，也就是该数组的最后一个元素
        // 如果该数组为空，得到的是一个 undefined

        // 最开始stack为空的时候直接添加
        const top = stack[stack.length - 1];
        if (!top) {
            stack.push(item);
        } else if (item.level > top.level) {

            // 进入此分支，说明当前的 toc 对象的等级比栈顶（之前的上一个）要大
            // 说明当前这个 toc 对象应该成为上一个 toc 对象的子元素

            // 下一个进来的元素如果等级比上一个添加的小就让他作为前一个的子元素，然后向stack中添加使得成为下一个比较对象

            top.children.push(item);
            stack.push(item);
        } else {
            // 如果这个元素等级相等时，则会剔除最后一个元素，然后再次进入到比较当中，观察是否是子元素进行添加
            // 如果大于的时候则会一个一个剔除向上知道数组清空再从新添加执行比较
            stack.pop();
            handleItem(item);
        }
    }

    let min = 6; // 标题最小的级别


    // 该 for 循环用于寻找当前数组中最小的标题等级
    // 相当于找到最高的父级标题
    for (const i of flatArr) {
        if (i.lvl < min) {
            min = i.lvl;
        }
    }

    for (const item of flatArr) {
        const tocItem = createTOCItem(item);
        // 解释为 如果进去的时候已经的最小的标题了，就直接添加进去,保证了同标题没有子标题的内容直接返回
        if (tocItem.level === min) {
            // 如果进入此 if，说明当前的 toc 对象已经是最低的等级，不会作为其他对象的 children
            result.push(tocItem);
        }
        // 如果没有进入上面的 if，说明该 toc 对象不是最低等级，可能是其他 toc 对象 children 数组里面的一员

        // 并不是最小的标题等级时进入这个方法
        handleItem(tocItem);
    }
    return result;
}

// 处理 TOC
/**
 *  
 * @param {*} info 
 * @returns 
 */
module.exports.handleTOC = function(info) {
    let result = toc(info.markdownContent).json;
    // console.log(result);
    // 经过上面 toc 方法的处理，就将整个 markdown 里面的标题全部提取出来了

    // 接下来对上面的数据进行一个转换
    // 经过转换之后，toc 就转为了我们想要的格式
    info.toc = transfer(result);



    delete info.markdownContent;

    // 接下来再为各个级别的标题添加上 id
    for (const i of result) {
        switch (i.lvl) {
            case 1:
                {
                    var newStr = `<h1 id="${i.slug}">`;
                    info.htmlContent = info.htmlContent.replace('<h1>', newStr);
                    break;
                }
            case 2:
                {
                    var newStr = `<h2 id="${i.slug}">`;
                    info.htmlContent = info.htmlContent.replace('<h2>', newStr);
                    break;
                }
            case 3:
                {
                    var newStr = `<h3 id="${i.slug}">`;
                    info.htmlContent = info.htmlContent.replace('<h3>', newStr);
                    break;
                }
            case 4:
                {
                    var newStr = `<h4 id="${i.slug}">`;
                    info.htmlContent = info.htmlContent.replace('<h4>', newStr);
                    break;
                }
            case 5:
                {
                    var newStr = `<h5 id="${i.slug}">`;
                    info.htmlContent = info.htmlContent.replace('<h5>', newStr);
                    break;
                }
            case 6:
                {
                    var newStr = `<h6 id="${i.slug}">`;
                    info.htmlContent = info.htmlContent.replace('<h6>', newStr);
                    break;
                }
        }
    }
    info.toc = JSON.stringify(info.toc)
    return info;
}